package com.crazy.common.ueditor;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

import javax.servlet.ServletContext;

import org.springframework.web.multipart.MultipartFile;

/**
 * UEditor文件上传辅助类
 * 
 * @author zhangweiwei
 */
public class Uploader {
	private static HashMap<String, String> errorInfo;
	public static final String fileDir = "/upload";
	private static String[] fileType = { ".gif", ".png", ".jpg", ".jpeg",
			".bmp" };
	public static final String separate = "ue_separate_ue";
	static {
		errorInfo = new HashMap<String, String>();
		errorInfo.put("SUCCESS", "SUCCESS"); // 默认成功
		errorInfo.put("NOFILE", "未包含文件上传域");
		errorInfo.put("TYPE", "不允许的文件格式");
		errorInfo.put("SIZE", "文件大小超出限制");
		errorInfo.put("ENTYPE", "请求类型ENTYPE错误");
		errorInfo.put("REQUEST", "上传请求异常");
		errorInfo.put("IO", "IO异常");
		errorInfo.put("DIR", "目录创建失败");
		errorInfo.put("UNKNOWN", "未知错误");
	}

	/**
	 * 获取指定目录下所有文件
	 * 
	 * @param realpath
	 * @param files
	 * @return
	 */
	public static List<File> getFiles(String realpath, List<File> files) {
		File realFile = new File(realpath);
		if (realFile.isDirectory()) {
			File[] subfiles = realFile.listFiles();
			for (File file : subfiles) {
				if (file.isDirectory()) {
					getFiles(file.getAbsolutePath(), files);
				} else {
					if (!getFileType(file.getName()).equals("")) {
						files.add(file);
					}
				}
			}
		}
		return files;
	}

	/**
	 * 获取文件类型
	 * 
	 * @param fileName
	 * @return
	 */
	private static String getFileType(String fileName) {
		for (String ft : fileType) {
			if (fileName.toLowerCase().endsWith(ft)) {
				return ft;
			}
		}
		return "";
	}

	// 文件允许格式
	private String[] allowFiles = { ".rar", ".doc", ".docx", ".zip", ".pdf",
			".txt", ".swf", ".wmv", ".gif", ".png", ".jpg", ".jpeg", ".bmp" };
	private ServletContext context;
	private String fileName = "";// 上传文件名
	private String originalName = "";// 原始文件名
	private String savePath = fileDir;// 保存路径
	private String state = "";// 状态
	private String title = "";
	private String type = "";// 文件类型
	private String url = "";// 输出文件地址

	public Uploader(ServletContext context) {
		this.context = context;
	}

	/**
	 * 文件类型判断
	 * 
	 * @author zhangweiwei
	 * @param fileName
	 * @return
	 */
	private boolean checkFileType(String fileName) {
		if (fileName == null) {
			return false;
		}
		for (String ext : this.allowFiles) {
			if (fileName.toLowerCase().endsWith(ext)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 获取文件扩展名
	 * 
	 * @return string
	 */
	private String getFileExt(String fileName) {
		this.type = fileName.substring(fileName.lastIndexOf("."));
		return this.type;
	}

	public String getFileName() {
		return this.fileName;
	}

	/**
	 * 根据字符串创建本地目录 并按照日期建立子目录返回
	 * 
	 * @param path
	 * @return
	 */
	private String getFolder(String path) {
		SimpleDateFormat formater = new SimpleDateFormat("yyyyMMdd");
		path += "/" + formater.format(new Date());
		File dir = new File(this.getPhysicalPath(path));
		if (!dir.exists()) {
			try {
				dir.mkdirs();
			} catch (Exception e) {
				e.printStackTrace();
				this.state = errorInfo.get("DIR");
				return "";
			}
		}
		return path;
	}

	/**
	 * 依据原始文件名生成新文件名
	 * 
	 * @return
	 */
	private String getName(String fileName) {
		Random random = new Random();
		this.fileName = "" + random.nextInt(10000) + System.currentTimeMillis()
				+ this.getFileExt(fileName);
		return this.fileName;
	}

	public String getOriginalName() {
		return this.originalName;
	}

	/**
	 * 根据传入的虚拟路径获取物理路径
	 * 
	 * @author zhangweiwei
	 * @param path
	 * @return
	 */
	private String getPhysicalPath(String path) {
		String realPath = this.context.getRealPath("/");
		path = realPath + path;
		return path;
	}

	public String getState() {
		return this.state;
	}

	public String getTitle() {
		return this.title;
	}

	public String getType() {
		return this.type;
	}

	public String getUrl() {
		return this.url;
	}

	public void setAllowFiles(String[] allowFiles) {
		this.allowFiles = allowFiles;
	}

	public void setOriginalName(String originalName) {
		this.originalName = originalName;
	}

	public void setSavePath(String savePath) {
		this.savePath = savePath;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	/**
	 * 文件上传
	 * 
	 * @author zhangweiwei
	 * @param upfile
	 * @throws Exception
	 */
	public void upload(MultipartFile upfile) throws Exception {
		OutputStream os = null;
		try {
			if (upfile == null) {
				this.state = errorInfo.get("NOFILE");
				return;
			}
			if (!this.checkFileType(this.originalName)) {
				this.state = errorInfo.get("TYPE");
				return;
			}
			savePath = this.getFolder(this.savePath);
			this.fileName = this.getName(this.originalName);
			this.url = savePath + "/" + this.fileName;
			String parent = this.context.getRealPath(savePath);
			File dest = new File(parent, this.fileName);
			os = new FileOutputStream(dest);
			os.write(upfile.getBytes());
			this.state = errorInfo.get("SUCCESS");
		} catch (Exception e) {
			this.state = errorInfo.get("UNKNOWN");
			e.printStackTrace();
		} finally {
			if (os != null) {
				os.flush();
				os.close();
			}
		}
	}
}
